﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Windows.Forms;

namespace VersionComparer.UI.ExtendedTreeView
{
    [Serializable]
    public class SelectableTreeNode : TreeNode
    {
        #region fields
        bool loaded = false;
        List<TreeNode> temporaryNodes = new List<TreeNode>();
        bool selected;
        Color backColor = Color.Empty;
        Color foreColor = Color.Black;
        #endregion fields

        #region constructors

        protected SelectableTreeNode(SerializationInfo info, StreamingContext context)
            : base(info, context)
        { }

        public SelectableTreeNode()
        {
            SelectedEventEnabled = true;
        }
        #endregion constructors

        #region properties

        public bool SelectedEventEnabled
        {
            get;
            set;
        }
        public bool Selected
        {
            get
            {
                return selected;
            }
            set
            {

                if (selected != value)
                {
                    selected = value;
                    if (!selected)
                    {
                        BackColor = backColor;
                        ForeColor = foreColor;
                    }
                    else
                    {
                        ForeColor = Color.White;
                        BackColor = Color.FromArgb(50, 100, 220);
                        //BackColor = Color.Gray;
                    }
                    if (SelectedEventEnabled && TreeView != null)
                        (this.TreeView as MultiSelectTreeView).OnAfterMultiSelect(new TreeViewEventArgs(this));
                }
            }
        }
        
        public int NodesCount
        {
            get
            {
                return Nodes.Count + temporaryNodes.Count;
            }
        }
        private bool allExpanded = false;
        protected bool Expanded
        {
            get;
            set;
        }
        protected bool AllExpanded
        {
            get
            {
                if (allExpanded )
                    return true;

                SelectableTreeNode parent = Parent as SelectableTreeNode;
                if  (parent == null )
                    return false;
                else
                    return parent.AllExpanded;
            }
            set
            {
                allExpanded = value;
            }
        }
        #endregion properties

        public TreeNode[] AllNodes
        {
            get
            {
                List<TreeNode> aux = new List<TreeNode>();
                foreach (TreeNode node in Nodes)
                    aux.Add(node);
                aux.AddRange(temporaryNodes);
                return aux.ToArray();
            }
        }
        public TreeNode Node(int i)
        {
            if (i >= Nodes.Count)
            {
                if (i - Nodes.Count >= temporaryNodes.Count)
                    return null;
                return temporaryNodes[i - Nodes.Count];
            }
            else
                return Nodes[i];
        }

        public void CollapseNode()
        {
            Expanded = false;
            AllExpanded = false;
        }
        public void ExpandNode()
        {
            Expanded = true;
            Nodes.AddRange(temporaryNodes.ToArray ());
            temporaryNodes.Clear();
            EnsureLoaded(2);
            Expand();
        }

        public void CollapseAll()
        {
            AllExpanded = false;
            base.Collapse();
        }
        public new void ExpandAll()
        {
            AllExpanded = true;
            base.ExpandAll();
        }
        public void RemoveNode(TreeNode node)
        {
            if (temporaryNodes.Contains(node))
                temporaryNodes.Remove(node);
            else
                Nodes.Remove(node);

        }
        public void RemoveNode(int i)
        {
            if (i >= Nodes.Count)
                temporaryNodes.RemoveAt(i - Nodes.Count);
            else
                Nodes.RemoveAt (i);
        }
        public void AddNodes(params TreeNode [] nodes)
        {
            if (loaded)
                Nodes.AddRange(nodes);
            else
                temporaryNodes.AddRange(nodes);
            //Nodes.AddRange(nodes);
        }
        protected void CopyColorsFrom(SelectableTreeNode node)
        {
            ForeColor = node.ForeColor;
            BackColor = node.BackColor;
            backColor = node.backColor;
            foreColor = node.foreColor;
        }
        public void SetBackColor(Color newBackColor)
        {
            if (newBackColor != Color.Empty)
            {
            }
            backColor = newBackColor;
            if (!Selected)
                BackColor = backColor;
        }
        public void SetForeColor(Color newForeColor)
        {
            foreColor = newForeColor;
            if (!Selected)
                ForeColor = foreColor;
        }
        protected virtual void OnEnsureLoaded()
        {
            if (temporaryNodes.Count > 0)
            {
                Nodes.AddRange(temporaryNodes.ToArray());
                temporaryNodes.Clear();
                
            }
            loaded = true;
        }
        protected void EnsureLoaded(int deep)
        {
            OnEnsureLoaded();
            deep--;
                
            if (deep > 0)
            {
                foreach (SelectableTreeNode node in Nodes)
                    node.EnsureLoaded(deep);
            }
        }
        public void OnExpand()
        {
            EnsureLoaded(2);
            Expanded = true;
        }
        
    }
}
